home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 …ember: Reference Library / Dev.CD Dec 94.toast / Periodicals / develop / develop Issue 20 / develop 20 code / Advanced AOCE Templates / Orbits.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-23  |  13.1 KB  |  495 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Orbits.c
  3.  
  4.     Contains:    Planetary orbit display templates
  5.  
  6.     Written by:    Harry Chesley
  7.  
  8.     Copyright:    © 1994 by Apple Computer, Inc.
  9.  
  10.     Change History (most recent first):
  11.  
  12.                    5/25/94    hrc        created
  13.  
  14.     To Do:
  15. */
  16.  
  17. #include <SANE.h>
  18. #include <String.h>
  19. #include <Packages.h>
  20. #include <Script.h>
  21. #include <OSUtils.h>
  22. #include <Math.h>
  23. #include <Quickdraw.h>
  24. #include <TextUtils.h>
  25. #include "OCETemplates.h"
  26. #include "Orbits.h"
  27.  
  28. OSErr instanceInit(DETCallBlockPtr);
  29. OSErr idle(DETCallBlockPtr);
  30. OSErr convertToRString(DETCallBlockPtr);
  31. OSErr convertFromRString(DETCallBlockPtr);
  32. OSErr propertyDirtied(DETCallBlockPtr);
  33. OSErr updateOrbitEntries(DETCallBlockPtr);
  34. OSErr customViewDraw(DETCallBlockPtr);
  35.  
  36. unsigned long getNumberProperty(DETCallBlockPtr, short);
  37. extended getExtendedProperty(DETCallBlockPtr, short);
  38. LongDateTime getTimeProperty(DETCallBlockPtr, short);
  39. OSErr setSublistTimeProperty(DETCallBlockPtr, short property, long itemNumber, LongDateTime);
  40.  
  41. pascal OSErr Orbits(DETCallBlockPtr callBlockPtr)
  42.     {
  43.     if (callBlockPtr->protoCall.target.selector == kDETSelf)
  44.         switch (callBlockPtr->protoCall.reqFunction)
  45.             {
  46.             case kDETcmdInstanceInit:        return instanceInit(callBlockPtr);
  47.             case kDETcmdIdle:                return idle(callBlockPtr);
  48.             case kDETcmdConvertToRString:    return convertToRString(callBlockPtr);
  49.             case kDETcmdConvertFromRString:    return convertFromRString(callBlockPtr);
  50.             case kDETcmdPropertyDirtied:    return propertyDirtied(callBlockPtr);
  51.             case kDETcmdCustomViewDraw:        return customViewDraw(callBlockPtr);
  52.             }
  53.  
  54.     else if (callBlockPtr->protoCall.reqFunction == kDETcmdInit)
  55.         {
  56.         callBlockPtr->init.newCallFors = kDETCallForIdle + kDETCallForViewChanges;
  57.         return noErr;
  58.         }
  59.  
  60.     return kDETDidNotHandle;
  61.     }
  62.  
  63. void setTimeToNow(DETCallBlockPtr callBlockPtr)
  64.     {
  65.     unsigned long l;
  66.     LongDateTime ldt, oldLdt;
  67.     DETSetPropertyBinaryBlock spb;
  68.  
  69.     // Get the old time
  70.     oldLdt = getTimeProperty(callBlockPtr, kOrbitsTimeProperty);
  71.     // Get the current time
  72.     GetDateTime(&l);
  73.     ldt = l;
  74.     // Only change if it's different
  75.     if (ldt != oldLdt)
  76.         {
  77.         // Set the property value
  78.         spb.reqFunction = kDETcmdSetPropertyBinary;
  79.         spb.target = callBlockPtr->protoCall.target;
  80.         spb.property = kOrbitsTimeProperty;
  81.         spb.newValue = (Ptr) &ldt;
  82.         spb.newValueSize = sizeof(ldt);
  83.         if (CallBackDET(callBlockPtr, (DETCallBackBlock*) &spb) == noErr)
  84.             {
  85.             // Dirty the property (force updates)
  86.             DETDirtyPropertyBlock dp;
  87.     
  88.             dp.reqFunction = kDETcmdDirtyProperty;
  89.             dp.target = callBlockPtr->protoCall.target;
  90.             dp.property = kOrbitsTimeProperty;
  91.             CallBackDET(callBlockPtr, (DETCallBackBlock*) &dp);
  92.             dp.property = kOrbitsCustomViewProperty;
  93.             CallBackDET(callBlockPtr, (DETCallBackBlock*) &dp);
  94.             }
  95.         }
  96.     }
  97.  
  98. OSErr instanceInit(DETCallBlockPtr callBlockPtr)
  99.     {
  100.     // Set the time property type
  101.     DETSetPropertyTypeBlock spt;
  102.  
  103.     spt.reqFunction = kDETcmdSetPropertyType;
  104.     spt.target = callBlockPtr->protoCall.target;
  105.     spt.property = kOrbitsTimeProperty;
  106.     spt.newType = kTimePropertyType;
  107.     CallBackDET(callBlockPtr, (DETCallBackBlock*) &spt);
  108.  
  109.     setTimeToNow(callBlockPtr);
  110.  
  111.     return noErr;
  112.     }
  113.  
  114. OSErr idle(DETCallBlockPtr callBlockPtr)
  115.     {
  116.     // Update time if requested
  117.     if (getNumberProperty(callBlockPtr, kOrbitsNowProperty)) setTimeToNow(callBlockPtr);
  118.     return noErr;
  119.     }
  120.  
  121. OSErr convertToRString(DETCallBlockPtr callBlockPtr)
  122.     {
  123.     DETConvertToRStringBlock* ctrs;
  124.     DETGetPropertyTypeBlock gpt;
  125.  
  126.     ctrs = &(callBlockPtr->convertToRString);
  127.  
  128.     // Get the type of the property being converted
  129.     gpt.reqFunction = kDETcmdGetPropertyType;
  130.     gpt.target = ctrs->target;
  131.     gpt.property = ctrs->property;
  132.     if (CallBackDET(callBlockPtr, (DETCallBackBlock*) &gpt) == noErr)
  133.         {
  134.         char s[256];
  135.         RStringHandle h;
  136.  
  137.         // Convert time properties
  138.         if (gpt.propertyType == kTimePropertyType)
  139.             {
  140.             LongDateTime ldt;
  141.             char tStr[256];
  142.  
  143.             // Get the current value
  144.             ldt = getTimeProperty(callBlockPtr, ctrs->property);
  145.  
  146.             // Convert it to a string
  147.             iuldatestring(&ldt, shortDate, s, nil);
  148.             tStr[0] = ' ';
  149.             tStr[1] = 0;
  150.             strcat(s, tStr);
  151.             iultimestring(&ldt, true, tStr, nil);
  152.             strcat(s, tStr);
  153.             }
  154.  
  155.         else return kDETDidNotHandle;
  156.  
  157.         // Return the string as an RString handle
  158.         h = (RStringHandle) NewHandle(strlen(s) + sizeof(ProtoRString));
  159.         if (h)
  160.             {
  161.             HLock((Handle) h);
  162.             OCECToRString(s, smRoman, *h, strlen(s));
  163.             HUnlock((Handle) h);
  164.             ctrs->theValue = h;
  165.  
  166.             return noErr;
  167.             }
  168.         else return MemError();
  169.         }
  170.  
  171.     return kDETDidNotHandle;
  172.     }
  173.  
  174. OSErr convertFromRString(DETCallBlockPtr callBlockPtr)
  175.     {
  176.     OSErr retVal;
  177.     DETConvertFromRStringBlock* cfrs;
  178.     DETGetPropertyTypeBlock gpt;
  179.  
  180.     retVal = kDETDidNotHandle;
  181.     cfrs = &(callBlockPtr->convertFromRString);
  182.  
  183.     // Get the property type to convert
  184.     gpt.reqFunction = kDETcmdGetPropertyType;
  185.     gpt.target = cfrs->target;
  186.     gpt.property = cfrs->property;
  187.     if (CallBackDET(callBlockPtr, (DETCallBackBlock*) &gpt) == noErr)
  188.         {
  189.         char* str;
  190.  
  191.         // Convert the RString into a string
  192.         str = ((char*) &cfrs->theValue->dataLength) + 1;
  193.         p2cstr(str);
  194.  
  195.         // Convert time properties
  196.         if (gpt.propertyType == kTimePropertyType)
  197.             {
  198.             DateCacheRecord dc;
  199.  
  200.             // Init the date cache
  201.             if (InitDateCache(&dc) == noErr)
  202.                 {
  203.                 long lengthUsed;
  204.                 LongDateRec ldr;
  205.                 LongDateTime ldt;
  206.                 long strLength;
  207.                 DETSetPropertyBinaryBlock spb;
  208.  
  209.                 // Convert the string to a time
  210.                 strLength = strlen(str);
  211.                 String2Date(str, strLength, &dc, &lengthUsed, &ldr);
  212.                 if ((strLength - lengthUsed) <= 0)
  213.                     {
  214.                     ldr.ld.hour = 0;
  215.                     ldr.ld.minute = 0;
  216.                     ldr.ld.second = 0;
  217.                     }
  218.                 else String2Time(str + lengthUsed, strLength - lengthUsed, &dc, &lengthUsed, &ldr);
  219.                 LongDate2Secs(&ldr, &ldt);
  220.  
  221.                 // Set the property value
  222.                 spb.reqFunction = kDETcmdSetPropertyBinary;
  223.                 spb.target = cfrs->target;
  224.                 spb.property = cfrs->property;
  225.                 spb.newValue = (Ptr) &ldt;
  226.                 spb.newValueSize = sizeof(ldt);
  227.                 if (CallBackDET(callBlockPtr, (DETCallBackBlock*) &spb) == noErr)
  228.                     {
  229.                     // Mark it as changed
  230.                     DETSetPropertyChangedBlock spc;
  231.                     spc.reqFunction = kDETcmdSetPropertyChanged;
  232.                     spc.target = cfrs->target;
  233.                     spc.property = cfrs->property;
  234.                     spc.propertyChanged = true;
  235.                     CallBackDET(callBlockPtr, (DETCallBackBlock*) &spc);
  236.                     }
  237.  
  238.                 retVal = noErr;
  239.                 }
  240.             }
  241.  
  242.         c2pstr(str);
  243.         }
  244.  
  245.     return retVal;
  246.     }
  247.  
  248. OSErr propertyDirtied(DETCallBlockPtr callBlockPtr)
  249.     {
  250.     DETPropertyDirtiedBlock* pd;
  251.  
  252.     // Check if we're interested in this property
  253.     pd = (DETPropertyDirtiedBlock*) &callBlockPtr->propertyDirtied;
  254.     switch (pd->property)
  255.         {
  256.         case kOrbitsTimeProperty:
  257.             updateOrbitEntries(callBlockPtr);
  258.             return noErr;
  259.         }
  260.  
  261.     return kDETDidNotHandle;
  262.     }
  263.  
  264. OSErr updateOrbitEntries(DETCallBlockPtr callBlockPtr)
  265.     {
  266.     LongDateTime ldt;
  267.     long i;
  268.  
  269.     // Get the time from the time field
  270.     ldt = getTimeProperty(callBlockPtr, kOrbitsTimeProperty);
  271.  
  272.     // Set the time in each sublist entry
  273.     for (i = 1;; i++)
  274.         if (setSublistTimeProperty(callBlockPtr, kTimeProperty, i, ldt) != noErr) break;
  275.  
  276.     return noErr;
  277.     }
  278.  
  279. unsigned long getNumberProperty(DETCallBlockPtr callBlockPtr, short property)
  280.     {
  281.     DETGetPropertyNumberBlock gpn;
  282.  
  283.     gpn.reqFunction = kDETcmdGetPropertyNumber;
  284.     gpn.target = callBlockPtr->protoCall.target;
  285.     gpn.property = property;
  286.     if (CallBackDET(callBlockPtr, (DETCallBackBlock*) &gpn) != noErr) return 0;
  287.  
  288.     return gpn.propertyValue;
  289.     }
  290.  
  291. extended getExtendedProperty(DETCallBlockPtr callBlockPtr, short property)
  292.     {
  293.     DETGetPropertyBinaryBlock gpb;
  294.     extended n;
  295.  
  296.     gpb.reqFunction = kDETcmdGetPropertyBinary;
  297.     gpb.target = callBlockPtr->protoCall.target;
  298.     gpb.property = property;
  299.     if (CallBackDET(callBlockPtr, (DETCallBackBlock*) &gpb) != noErr) return 0.0;
  300.  
  301.     BlockMove(*gpb.propertyValue, (char*) &n, sizeof(n));
  302.     DisposHandle(gpb.propertyValue);
  303.  
  304.     return n;
  305.     }
  306.  
  307. LongDateTime getTimeProperty(DETCallBlockPtr callBlockPtr, short property)
  308.     {
  309.     DETGetPropertyBinaryBlock gpb;
  310.     LongDateTime ldt;
  311.  
  312.     gpb.reqFunction = kDETcmdGetPropertyBinary;
  313.     gpb.target = callBlockPtr->protoCall.target;
  314.     gpb.property = property;
  315.     if (CallBackDET(callBlockPtr, (DETCallBackBlock*) &gpb) != noErr) return 0;
  316.  
  317.     BlockMove(*gpb.propertyValue, (char*) &ldt, sizeof(ldt));
  318.     DisposHandle(gpb.propertyValue);
  319.  
  320.     return ldt;
  321.     }
  322.  
  323. OSErr setSublistTimeProperty(DETCallBlockPtr callBlockPtr, short property, long itemNumber, LongDateTime ldt)
  324.     {
  325.     DETSetPropertyBinaryBlock spb;
  326.     OSErr retVal;
  327.  
  328.     spb.reqFunction = kDETcmdSetPropertyBinary;
  329.     spb.target.selector = kDETSublistItem;
  330.     spb.target.aspectName = nil;
  331.     spb.target.itemNumber = itemNumber;
  332.     spb.property = property;
  333.     spb.newValue = (Ptr) &ldt;
  334.     spb.newValueSize = sizeof(ldt);
  335.     retVal = CallBackDET(callBlockPtr, (DETCallBackBlock*) &spb);
  336.     if (retVal == noErr)
  337.         {
  338.         DETDirtyPropertyBlock dp;
  339.     
  340.         dp.reqFunction = kDETcmdDirtyProperty;
  341.         dp.target.selector = kDETSublistItem;
  342.         dp.target.aspectName = nil;
  343.         dp.target.itemNumber = itemNumber;
  344.         dp.property = kOrbitsTimeProperty;
  345.         retVal = CallBackDET(callBlockPtr, (DETCallBackBlock*) &dp);
  346.         }
  347.  
  348.     return retVal;
  349.     }
  350.  
  351. OSErr getSublistExtendedProperty(DETCallBlockPtr callBlockPtr, long itemNumber, short property, extended* n)
  352.     {
  353.     DETGetPropertyBinaryBlock gpb;
  354.     OSErr retVal;
  355.  
  356.     gpb.reqFunction = kDETcmdGetPropertyBinary;
  357.     gpb.target.selector = kDETSublistItem;
  358.     gpb.target.aspectName = nil;
  359.     gpb.target.itemNumber = itemNumber;
  360.     gpb.property = property;
  361.     retVal = CallBackDET(callBlockPtr, (DETCallBackBlock*) &gpb);
  362.     if (retVal != noErr) return retVal;
  363.     BlockMove(*gpb.propertyValue, (char*) n, sizeof(*n));
  364.  
  365.     return noErr;
  366.     }
  367.  
  368. OSErr getSublistPosition(DETCallBlockPtr callBlockPtr, long itemNumber, LongDateTime ldt, extended* x, extended* y)
  369.     {
  370.     DETGetPropertyBinaryBlock gpb;
  371.     OSErr retVal;
  372.  
  373.     // Set the time
  374.     retVal = setSublistTimeProperty(callBlockPtr, kTimeProperty, itemNumber, ldt);
  375.     if (retVal != noErr) return retVal;
  376.  
  377.     // Get x
  378.     retVal = getSublistExtendedProperty(callBlockPtr, itemNumber, kXProperty, x);
  379.     if (retVal != noErr) return retVal;
  380.  
  381.     // Get y
  382.     gpb.property = kYProperty;
  383.     retVal = getSublistExtendedProperty(callBlockPtr, itemNumber, kYProperty, y);
  384.     if (retVal != noErr) return retVal;
  385.  
  386.     return noErr;
  387.     }
  388.  
  389. OSErr customViewDraw(DETCallBlockPtr callBlockPtr)
  390.     {
  391.     DETGetCustomViewBoundsBlock gcvb;
  392.     OSErr retVal;
  393.     DETGetPropertyRStringBlock gpr;
  394.     long showOrbits;
  395.     LongDateTime ldt;
  396.     short halfWidth, halfHeight, centerX, centerY;
  397.     extended x, y;
  398.     extended largestDistance;
  399.     extended scaleFactor;
  400.     long i;
  401.     Rect r;
  402.  
  403.     // If this isn't for our view, then ignore it
  404.     if (callBlockPtr->protoCall.property != kOrbitsCustomViewProperty) return kDETDidNotHandle;
  405.  
  406.     // Get the bounds of the view
  407.     gcvb.reqFunction = kDETcmdGetCustomViewBounds;
  408.     gcvb.target = callBlockPtr->protoCall.target;
  409.     gcvb.property = callBlockPtr->protoCall.property;
  410.     retVal = CallBackDET(callBlockPtr, (DETCallBackBlock*) &gcvb);
  411.     if (retVal != noErr) return retVal;
  412.  
  413.     // Figure the center
  414.     halfWidth = (gcvb.bounds.right - gcvb.bounds.left) / 2;
  415.     halfHeight = (gcvb.bounds.bottom - gcvb.bounds.top) / 2;
  416.     centerX = gcvb.bounds.left + halfWidth;
  417.     centerY = gcvb.bounds.top + halfHeight;
  418.  
  419.     // Draw space
  420.     PaintRect(&gcvb.bounds);
  421.  
  422.     // Draw the sun
  423.     ForeColor(whiteColor);
  424.     r.top = centerY - 4; r.bottom = centerY + 4;
  425.     r.left = centerX - 4; r.right = centerX + 4;
  426.     PaintOval(&r);
  427.  
  428.     // Get the time
  429.     ldt = getTimeProperty(callBlockPtr, kOrbitsTimeProperty);
  430.  
  431.     // Guess the max size
  432.     largestDistance = 0.0;
  433.     for (i = 1;; i++)
  434.         {
  435.         extended newDistance;
  436.         if (getSublistPosition(callBlockPtr, i, ldt, &x, &y) != noErr) break;
  437.         newDistance = sqrt(x*x + y*y);
  438.         if (newDistance > largestDistance) largestDistance = newDistance;
  439.         }
  440.     scaleFactor = (halfHeight - 15) / largestDistance;
  441.  
  442.     // Plot everyone
  443.     showOrbits = getNumberProperty(callBlockPtr, kOrbitsCustomViewProperty);
  444.     TextFont(kDETApplicationFont);
  445.     TextSize(9);
  446.     gpr.reqFunction = kDETcmdGetPropertyRString;
  447.     gpr.target.selector = kDETSublistItem;
  448.     gpr.target.aspectName = nil;
  449.     gpr.property = kDETPrName;
  450.     for (i = 1;; i++)
  451.         {
  452.         // Draw the body
  453.         if (getSublistPosition(callBlockPtr, i, ldt, &x, &y) != noErr) break;
  454.         r.top = centerY - ((short) rint(scaleFactor*y)) - 1; r.bottom = r.top + 3;
  455.         r.left = centerX + ((short) rint(scaleFactor*x)) - 1; r.right = r.left + 3;
  456.         PaintOval(&r);
  457.  
  458.         // Draw the name
  459.         gpr.target.itemNumber = i;
  460.         if ((CallBackDET(callBlockPtr, (DETCallBackBlock*) &gpr) == noErr) && ((*gpr.propertyValue)->dataLength < 256))
  461.             {
  462.             HLock((Handle) gpr.propertyValue);
  463.             MoveTo(r.right + 1, r.top < centerY ? r.top - 1 : r.bottom + 10);
  464.             DrawString(((char*) &(*gpr.propertyValue)->dataLength) + 1);
  465.             DisposHandle((Handle) gpr.propertyValue);
  466.             }
  467.  
  468.         // Show the future track (if requested)
  469.         if (showOrbits)
  470.             {
  471.             LongDateTime ldtInc;
  472.             extended orbitInc;
  473.             short j;
  474.  
  475.             if (getSublistExtendedProperty(callBlockPtr, i, kTpProperty, &orbitInc) != noErr) break;
  476.             // orbitInc is calculated such that 36 of them will produce a
  477.             // complete one year orbit
  478.             orbitInc *= (10.0*24.0*60.0*60.0);
  479.             for (j = 36, ldtInc = ldt + orbitInc; j--; ldtInc += orbitInc)
  480.                 {
  481.                 if (getSublistPosition(callBlockPtr, i, ldtInc, &x, &y) != noErr) break;
  482.                 r.left = centerX + ((short) rint(scaleFactor*x)); r.right = r.left + 1;
  483.                 r.top = centerY - ((short) rint(scaleFactor*y)); r.bottom = r.top + 1;
  484.                 PaintRect(&r);
  485.                 }
  486.             }
  487.         }
  488.  
  489.     // Return things to normal
  490.     ForeColor(blackColor);
  491.     updateOrbitEntries(callBlockPtr);
  492.  
  493.     return noErr;
  494.     }
  495.